package com.start;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import com.start.secure.encrypt.EncryptBase;
import com.start.secure.encrypt.EncryptXAES;
import com.start.secure.encrypt.XData;
import com.start.secure.encrypt.XKey;
import com.xpec.c4.game.system.InitData;
import com.xpec.c4.game.system.StartInfo;


/**
 * 會呼叫指定的啟動程序, 由我們自訂的class loader來啟動<br>
 * 這個是要被擾碼的<br>
 * 
 * @author yangbingyan
 *
 */
public class XStart {

	/**
	 * 
	 */
	private byte[] classBytes = null;
	
	/**
	 * 
	 */
	private String entryCode = "com.start.AuthorizeEntry";
	
	/**
	 * 
	 */
	private String classResourceName = "AuthorizeEntry.bin";
	
	/**
	 * 
	 */
	private String licenceAddress = "127.0.0.1";
	
	/**
	 * 
	 */
	private String licenceCommand = "/getlicense";
	
	/**
	 * Target port
	 */
	private String endpoint = "8080";
	
	/**
	 * 直接調用
	 */
	private boolean fromClass = false;

	/**
	 * 
	 */
	public boolean init(){
		
		String name = InitData.editorResourceRootPath + InitData.byteFolderPath + classResourceName;
		
		if(loadClass()){
			fromClass = true;
			return true;
		}
		else if(loadClassFromFile(name)){
			System.out.println("get AuthorizeEntry from Local");
			return decodeClass();
		}
		// 本地端没有, 从网路抓
		else if(receiveFromRemote()){
			System.out.println("get AuthorizeEntry from Remote");
			return decodeClass();
		}
			
		return false;
	}
	
	/**
	 * 
	 * @return
	 */
	private boolean decodeClass(){
		
		XData data = new XData();
		data.setEncodeData(classBytes);
		
		byte [] keyData = {120,112,101,99};
		XKey key = new XKey(keyData);
		
		EncryptBase encrypt = new EncryptXAES();
		
		if(encrypt.decode(data, key)){
			classBytes = data.getOriginData();
			return true;
		}
		return false;
	}
	
	/**
	 * 
	 * @return
	 */
	private boolean receiveFromRemote(){
		
		String requestString = "http://" + licenceAddress + ":" + endpoint + licenceCommand;
		String sjar = getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
		
		if(sjar != null){
			System.out.println(sjar);
			requestString = requestString + "?" + sjar;
		}

		HttpClient httpclient = new DefaultHttpClient();		
		HttpGet httpget = new HttpGet(requestString);
		HttpResponse response;
		try {
			
			InputStream instream = null;
			response = httpclient.execute(httpget);

			HttpEntity entity = response.getEntity();
			if (entity != null) {
				instream = entity.getContent();
				int cnt = (int) entity.getContentLength();				
				classBytes = new byte[cnt];				
				instream.read(classBytes, 0, cnt);
			}
			
			if(instream != null){
				instream.close();
				return true;
			}
			
		}catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}		
		
		return false;
	}
	

	/**
	 * 
	 * @return
	 */
	public boolean startup(String [] args, StartInfo startInfo){
		
		try {
			
			XClassLoader xLoader = new XClassLoader();
			Class<?> myClass = null;
			
			if(this.isFromClass()){
				myClass = xLoader.loadClass(entryCode);
			}else{

				if(classBytes == null || classBytes.length < 1){
					System.out.println("licence expired.");
					return false;
				}
				myClass = xLoader.loadClassEx(entryCode, classBytes);
			}
			
			Method main = myClass.getMethod("startup", new Class[] { String[].class, StartInfo.class });
			main.invoke(myClass.newInstance(), new Object[] { args, startInfo });

			System.out.println("haha end.");
			return true;
			
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch(InvocationTargetException e){
			e.printStackTrace();
		} catch(IllegalAccessException e){
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		}
		
		System.out.println("licence expired.");
		return false;
	}

	protected byte[] getClassBytes() {
		return classBytes;
	}

	public void setClassBytes(byte[] classBytes) {
		this.classBytes = classBytes;
	}
	
	/**
	 * 
	 * @param filename
	 * @return
	 */
	public boolean loadClassFromFile(String filename){
		
		InputStream input;
		
		try {
			
			input = new FileInputStream(filename);
			
			int cnt;
			cnt = input.available();
			
			if(cnt > 0){
				classBytes = new byte[cnt];
				input.read(classBytes, 0, cnt);
			}	
			
			input.close();
			
			return true;
			
		} catch (FileNotFoundException e) {
			// 授权数据错误
			// e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}		
	
		System.out.println("licence expired.");
		return false;
	}

	/**
	 * 
	 */
	public boolean isFromClass() {
		return fromClass;
	}

	protected void setFromClass(boolean fromClass) {
		this.fromClass = fromClass;
	}
	
	/**
	 * 
	 * @return
	 */
	private boolean loadClass(){
		
		try {
			new XClassLoader().loadClass(entryCode);
			// new XClassLoader().loadClass("");
			return true;
		} catch (ClassNotFoundException e) {
			// e.printStackTrace();
		}
		return false;
	}
	
}
